#include <string.h>
#include "../../../../mac/mac.h"

mac_init_test()
{
    mac_info_init();
    mac_retry_init();
    mac_indir_init();
    buf_init();
}

/* generate the association request frame, sent it,
   read it from the tx, parse it, compare it with
   the original associate requeset.
 */
int8 mac_assoc_req_cmp(mac_assoc_req_t *req)
{
    buf_t *buf;
    uint8 *tx_frm;
    uint8 l;
    mac_hdr_t hdr;
    mac_frm_assoc_req_t parse;
    int8 ret;

    /* initialize the buf for parsing frame */
    /*
    memset(&buf.array[0], 0, sizeof(buf.array));
    buf.length = 0;
    buf.ptr = &buf.array[127];
    */
    buf = buf_alloc(true);

    ret = mac_assoc_req(req);
    MAC_DEBUG("mac_assoc_req_cmp: return value of mac_assoc_req is %d\n", ret);
    /* now the association request has already in the tx frame */

    /* check the frame out, parse and compare it with req */
    tx_frm = get_tx_frm();
    l = get_tx_frm_len();
    MAC_DEBUG("mac_assoc_req_cmp: length of the generated frame is %d\n", l);
    /* back off the pointer */
    buf->ptr -= (l-1);
    memcpy(buf->ptr, tx_frm, l);

    /* parse the frame */
    mac_parse_hdr(buf, &hdr);
    mac_parse_cmd(buf); 
    mac_parse_assoc_req(buf, &parse);

    parse.src.mode = hdr.src_addr.mode;
    parse.src.a.addr64 = hdr.src_addr.a.addr64;
    parse.dest.mode = hdr.dest_addr.mode;
    parse.dest.a.addr64 = hdr.dest_addr.a.addr64;
    parse.src_pan_id = hdr.src_pan_id;
    parse.dest_pan_id = hdr.dest_pan_id;
    parse.dsn = hdr.dsn;

    MAC_DEBUG("mac_assoc_req_cmp: parse.src.mode is 0x%x\n", parse.src.mode);
    MAC_DEBUG("mac_assoc_req_cmp: parse.src.a.addr64 is 0x%x\n", (uint32)parse.src.a.addr64);
    MAC_DEBUG("mac_assoc_req_cmp: parse.dest.mode i 0x%x\n", parse.dest.mode);
    MAC_DEBUG("mac_assoc_req_cmp: parse.dest.a.addr64 is 0x%x\n", (uint32)parse.dest.a.addr64);
    MAC_DEBUG("mac_assoc_req_cmp: parse.dest_pan_id is 0x%x\n", parse.dest_pan_id);
    MAC_DEBUG("mac_assoc_req_cmp: parse.dsn is 0x%x\n", parse.dsn);
    
    MAC_DEBUG("\n");
    MAC_DEBUG("mac_assoc_req_cmp: req->coord.mode is 0x%x\n", req->coord.mode);
    MAC_DEBUG("mac_assoc_req_cmp: req->coord.a.addr16 is 0x%x\n", req->coord.a.addr16);
    MAC_DEBUG("mac_assoc_req_cmp: req->coord.a.addr64 is 0x%x\n", (uint32)req->coord.a.addr64);
    MAC_DEBUG("mac_assoc_req_cmp: req->cap_info is 0x%x\n", req->cap_info);
    MAC_DEBUG("mac_assoc_req_cmp: req->coord_pan_id is 0x%x\n", req->coord_pan_id);

    MAC_DEBUG("\nmac_assoc_req_cmp: got here\n");
    MAC_DEBUG("mac_assoc_req_cmp: coord.mode is %d\n", req->coord.mode);
    if (req->coord.mode == ADDR_64_M) {
        if (req->coord.a.addr64 != parse.dest.a.addr64) {
            buf_free(buf);
            return MAC_ERR;
        }
    } else {
        MAC_DEBUG("mac_assoc_req_cmp: got here\n");
        MAC_DEBUG("mac_assoc_req_cmp: addr16 is 0x%x\n", parse.dest.a.addr16);
        if (req->coord.a.addr16 != parse.dest.a.addr16) {
            buf_free(buf);
            return MAC_ERR;
        }
    }

    MAC_DEBUG("mac_assoc_req_cmp: mac state is %d\n", mac_get_state());
    if (req->coord_pan_id != parse.dest_pan_id ||
        req->coord.mode != parse.dest.mode ||
        req->cap_info != parse.cap_info ||
        mac_get_state() != mac_assoc_reqing
        /* coord addr, test above */
        ) {
        buf_free(buf);
        return MAC_ERR;
    }

    buf_free(buf);
    return 0;
}

int8 mac_assoc_resp_test(mac_assoc_resp_t *resp)
{
    buf_t *buf;
    buf_t *parse_buf;
    mac_indir_t *i;
    addr_t addr;
    uint8 *tx_frm;
    uint8 l;
    mac_hdr_t hdr;
    mac_frm_assoc_resp_t parse;
    int8 ret;

    buf = buf_alloc(true);
    if (buf == NULL) {
        return MAC_ERR;
    }

    ret = mac_assoc_resp(resp);
    if (ret != MAC_OK) {
        buf_free(buf);
        return MAC_ERR;
    }

    /* now the association request has already in the indir queue */
    /* check the frame out, parse and compare it with req */
    addr.mode = ADDR_64_M;
    addr.a.addr64 = resp->dest_addr;
    i = mac_indir_find(&addr);
    if (i == NULL || i->buf == NULL) {
        return MAC_ERR;
    }
    parse_buf = i->buf;

    /* parse the frame */
    mac_parse_hdr(parse_buf, &hdr);
    mac_parse_cmd(parse_buf); 
    mac_parse_assoc_resp(parse_buf, &parse);

    parse.src.mode = hdr.src_addr.mode;
    parse.dest.mode = hdr.dest_addr.mode;

    if (parse.src.mode == ADDR_16_M) {
        parse.src.a.addr16 = hdr.src_addr.a.addr16;
    } else if (parse.src.mode == ADDR_64_M) {
        parse.src.a.addr64 = hdr.src_addr.a.addr64;
    }

    if (parse.dest.mode == ADDR_16_M) {
        parse.dest.a.addr16 = hdr.dest_addr.a.addr16;
    } else if (parse.dest.mode == ADDR_64_M) {
        parse.dest.a.addr64 = hdr.dest_addr.a.addr64;
    }

    parse.dsn = hdr.dsn;
    parse.pan_id = hdr.dest_pan_id;
/*
typedef struct mac_assoc_resp_t_ {
    uint8 handle;
    int64 dest_addr;
    int16 short_addr;
    mac_status_t status;
} mac_assoc_resp_t;
*/
    MAC_DEBUG("mac_assoc_resp_test: got here\n");
    MAC_DEBUG("value of resp->dest_addr is 0x%x\n", resp->dest_addr);
    MAC_DEBUG("value of parse.dest.a.addr64 is 0x%x\n", parse.dest.a.addr64);
    if (resp->dest_addr != parse.dest.a.addr64) {
        buf_free(buf);
        mac_indir_free(parse.dsn);
        return MAC_ERR;
    }

    MAC_DEBUG("mac_assoc_resp_test: got here1\n");
    if (resp->short_addr != parse.short_addr) {
        buf_free(buf);
        mac_indir_free(parse.dsn);
        return MAC_ERR;
    }
    
    buf_free(buf);
    mac_indir_free(parse.dsn);
    return MAC_OK;
}


